#pragma once
#include "Message.hpp"
// size_t _line;           // ⾏号
// size_t _ctime;          // 时间
// std::thread::id _tid;   // 线程ID
// std::string _name;      // ⽇志器名称
// std::string _file;      // ⽂件名
// std::string _payload;   // ⽇志消息
// shw::level::value _level; // ⽇志等级
namespace shw
{
    class MsgFormat
    {
    public:
        using ptr = std::shared_ptr<MsgFormat>; // 方便管理
        virtual void format(std::ostream &out, const message &msg) = 0;
        virtual ~MsgFormat() {}
    };
    class LineFormatItem : public MsgFormat
    {
    public:
        LineFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override // 行号子类
        {
            out << msg._line;
        }
    };
    class TimeFormatItem : public MsgFormat
    {
    private:
        std::string _format;

    public:
        TimeFormatItem(const std::string &format = "%H:%M:%S") // 用缺省参数默认
            : _format(format)
        {
        }
        void format(std::ostream &out, const message &msg) override
        {
            struct tm *t = localtime(&msg._ctime);
            char buf[128] = {0};
            strftime(buf, 127, _format.c_str(), t); // 转换时间格式放在buf里面
            out << buf;
        }
    };
    class ThreadIdFormatItem : public MsgFormat // 线程ID子类
    {
    public:
        ThreadIdFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << msg._tid;
        }
    };
    class NameFormatItem : public MsgFormat // 日志器名称子类
    {
    public:
        NameFormatItem(const std::string &name = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << msg._name;
        }
    };
    class FileFormatItem : public MsgFormat // 文件子类
    {
    public:
        FileFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << msg._file;
        }
    };
    class PayLoadFormatItem : public MsgFormat // 日志消息子类
    {
    public:
        PayLoadFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << msg._payload;
        }
    };
    class LevelFormatItem : public MsgFormat // 等级子类
    {
    public:
        LevelFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << shw::level::ToString(msg._level);
        }
    };
    class TabFormatItem : public MsgFormat // 制表符子类
    {
    public:
        TabFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << "\t";
        }
    };
    class NLineFormatItem : public MsgFormat // 换行子类
    {
    public:
        NLineFormatItem(const std::string &str = ""){};
        void format(std::ostream &out, const message &msg) override
        {
            out << "\n";
        }
    };
    class OtherFormatItem : public MsgFormat // 其他子类
    {
    private:
        std::string _str;

    public:
        OtherFormatItem(const std::string &str = "") : _str(str) {}
        void format(std::ostream &out, const message &msg) override
        {
            out << _str;
        }
    };
    class Format
    {
    public:
        using ptr=std::shared_ptr<Format>;
        Format(const std::string &parten = "[%d{%H:%M:%S}][%t][%p][%c][%f:%l]%T%m%n") : _parten(parten) 
        {
            assert(ParseParten());
        }
        const std::string &Parten() { return _parten; } // 返回格式
        std::string format(const message &msg)
        {
            std::stringstream ss;
            format(ss, msg);
            return ss.str();
        }

    private:
        MsgFormat::ptr CreateItem(const std::string &c, const std::string &val = "")
        {
            if (c == "d")
                return std::make_shared<TimeFormatItem>(val); // 时间
            if (c == "t")
                return std::make_shared<ThreadIdFormatItem>(); // 线程ID
            if (c == "T")
                return std::make_shared<TabFormatItem>(); // 制表符缩进
            if (c == "p")
                return std::make_shared<LevelFormatItem>(); // 等级
            if (c == "c")
                return std::make_shared<NameFormatItem>(); // 日志器名称
            if (c == "f")
                return std::make_shared<FileFormatItem>(); // 文件名称
            if (c == "l")
                return std::make_shared<LineFormatItem>(); // 行号
            if (c == "m")
                return std::make_shared<PayLoadFormatItem>(); // 日志消息
            if (c == "n")
                return std::make_shared<NLineFormatItem>(); // 换行
            return std::make_shared<OtherFormatItem>(c);       // 其他消息
        }
        bool ParseParten()
        {
            size_t part1 = 0,part2=0;
            std::vector<std::pair<std::string, std::string>> fmat;
            size_t pos = 0;
            std::string key, value;
            while (pos < _parten.size())
            {
                if (_parten[pos] != '%') // 不是格式化字符那就是其他，直接添加
                {
                    key.push_back(_parten[pos++]);
                    continue;
                }
                // 走到这说明就是'%',但是还得判断是不是转义字符"%%"
                if (pos + 1 < _parten.size() && _parten[++pos] == '%')
                {
                    key.push_back(_parten[pos++]); // 转义字符，两个'%',直接添加
                    continue;
                }
                fmat.push_back(std::make_pair(key, value)); // 其他字符串格式添加
                key.clear();
                value.clear();
                key.push_back(_parten[pos]);
                if (pos + 1 < _parten.size() && _parten[pos + 1] == '{') // 是子项
                {

                    pos += 2;
                    while (pos < _parten.size() && _parten[pos] != '}')
                    {

                        value.push_back(_parten[pos++]);
                    }
                    if (pos >= _parten.size()) // 走完全部没有匹配到'}'
                    {
                        cout << "{}匹配失败，格式化字符串格式错误\n";
                        return false;
                    }
                }
                fmat.push_back(std::make_pair(key, value));

                key.clear();
                value.clear();
                pos++; // 更新下标
            }
            if(!key.empty())
            {
                fmat.push_back(std::make_pair(key, value)); // 最后一个其他字符串格式添加
            }

            for (auto &it : fmat) // 把子类指针放进vector中
            {
                _items.push_back(CreateItem(it.first, it.second));
            }
            return true;
        }
        void format(std::ostream &out, const message &msg) // 重载函数format
        {
            for (auto &it : _items)
            {
                it->format(out, msg);
            }
        }

    private:
        std::vector<MsgFormat::ptr> _items;
        std::string _parten; // 用户定义的格式化字符串
    };

}